-- 2D vector and matrix library in Lua

------------ angles ------------

function deg(a)
	return 57.295779513082322 * a
end

function rad(a)
	return .01745329251994 * a
end

function ang_norm(a)
	if (a > math.pi) then
		return a - 2 * math.pi
	elseif (a < -math.pi) then
		return a + 2 * math.pi
	else
		return a
	end
end

function ang_diff(b, a)
	return ang_norm(b - a)
end

------------ vector ------------

vec2 = 
{
	x = 0,
	y = 0
}

function vec2:new(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end

function vec2:init(px, py)
	local r = vec2:new()
	r.x = px
	r.y = py
	return r
end

function vec2.__add(a, b)
	local r = vec2:new()
	r.x = a.x + b.x
	r.y = a.y + b.y
	return r
end

function vec2.__sub(a, b)
	local r = vec2:new()
	r.x = a.x - b.x
	r.y = a.y - b.y
	return r
end

function vec2.__mul(a, b)
	local r = vec2:new()
	r.x = a * b.x
	r.y = a * b.y
	return r
end

function vec2.__unm(a)
	return vec2:init(-a.x, -a.y)
end

function vec2.__tostring(p)
	return '< ' .. p.x .. ', ' .. p.y .. '>'
end

function vec2:print()
	print(tostring(self))
end

function vec2:unpack()
	return self.x, self.y
end

function vec2:ang()
	return math.atan2(self.y, self.x)
end

function vec2:dir(s)
	return vec2:init(math.cos(s), math.sin(s))
end

function vec2:len()
	return math.sqrt(self.x * self.x + self.y * self.y)
end

function vec2:len2()
	return self.x * self.x + self.y * self.y
end

function vec2:normalize()
	local l = self:len()
	return vec2:init(self.x / l, self.y / l)
end

function dot(a, b)
	return a.x * b.x + a.y * b.y
end

function cross(a, b)
	return a.x * b.y - a.y * b.x
end

function dist(a, b)
	return (a - b):len()
end

------------ matrix ------------

-- stored row major: [a b; c d]

mat2 = 
{
	a = 1,
	b = 0,
	c = 0,
	d = 1
}

function mat2:new(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end

function mat2:init(pa, pb, pc, pd)
	local r = mat2:new()
	r.a = pa
	r.b = pb
	r.c = pc
	r.d = pd
	return r
end

function mat2.__add(a, b)
	local r = mat2:new()
	r.a = a.a + b.a
	r.b = a.b + b.b
	r.c = a.c + b.c
	r.d = a.d + b.d
	return r
end

function mat2.__sub(a, b)
	local r = mat2:new()
	r.a = a.a - b.a
	r.b = a.b - b.b
	r.c = a.c - b.c
	r.d = a.d - b.d
	return r
end

function mat2.__mul(a, b)
	local r = mat2:new()
	r.a = a * b.a
	r.b = a * b.b
	r.c = a * b.c
	r.d = a * b.d
	return r
end

function mat2.__unm(a)
	return mat2:init(-a.a, -a.b, -a.c, -a.d)
end

function mat2.__tostring(p)
	return '[ ' .. p.a .. ' ' .. p.b .. '; ' .. p.c .. ' ' .. p.d .. ']'
end

function mat2:print()
	print(tostring(self))
end

function mat2:unpack()
	return self.a, self.b, self.c, self.d
end

function rot(a)
	local s = math.sin(a)
	local c = math.cos(a)
	return mat2:init(c, -s, s, c)
end

function scale(a)
	return mat2:init(a, 0, 0, a)
end
